package yolorpc.fault.tolerant;

import lombok.extern.slf4j.Slf4j;
import yolorpc.model.RpcRequest;
import yolorpc.model.RpcResponse;
import yolorpc.proxy.ServiceProxyFactory;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * 降级到其他服务 - 容错策略
 */
@Slf4j
public class FailBackTolerantStrategy implements TolerantStrategy {

    @Override
    public RpcResponse doTolerant(Map<String, Object> context, Exception e) throws ClassNotFoundException {
        // 通过上下文获取请求内容
        RpcRequest rpcRequest = (RpcRequest) context.getOrDefault("rpcRequest", null);
        if (rpcRequest == null){
            log.info("======触发容错，返回上下文为空======");
            throw new RuntimeException(e.getMessage());
        }
        // 上下文不为空
        // 通过RpcRequest获取到该次调用的服务名
        String serviceName = rpcRequest.getServiceName();
        Class<?> serviceClass = Class.forName(serviceName);
        // 调用模拟接口
        Object proxy = null;
        Method method = null;
        Object invoke = null;
        try {
            proxy = ServiceProxyFactory.getProxy(serviceClass);
            method = proxy.getClass().getMethod(rpcRequest.getMethodName(), rpcRequest.getParameterTypes());
            invoke = method.invoke(proxy, rpcRequest.getArgs());
        } catch (Exception ex) {
            log.error("======获取模拟接口失败======");
            log.error(String.valueOf(ex));
            throw new RuntimeException(ex);
        }
        // 返回结果
        RpcResponse rpcResponse = new RpcResponse();
        rpcResponse.setData(invoke);
        rpcResponse.setDataType(method.getReturnType());
        rpcResponse.setMessage("fail back tolerant strategy");
        return rpcResponse;
    }
}
